---
title: Font
description: A library that allows loading fonts at runtime and using them in React Native components.
sourceCodeUrl: 'https://github.com/expo/expo/tree/sdk-53/packages/expo-font'
packageName: 'expo-font'
iconUrl: '/static/images/packages/expo-font.png'
platforms: ['android', 'ios', 'tvos', 'web']
---

import APISection from '~/components/plugins/APISection';
import { APIInstallSection } from '~/components/plugins/InstallSection';
import {
  ConfigReactNative,
  ConfigPluginExample,
  ConfigPluginProperties,
} from '~/ui/components/ConfigSection';
import { SnackInline } from '~/ui/components/Snippet';

`expo-font` allows loading fonts from the web and using them in React Native components. See more detailed usage information in the [Fonts](/develop/user-interface/fonts/) guide.

## Installation

<APIInstallSection />

## Configuration in app config

There are two ways to add fonts to your app: using the `expo-font` config plugin (recommended) or loading them at runtime.

The plugin allows you to embed font files at build time which is more efficient than [`useFonts`](#usefontsmap) or [`loadAsync`](#loadasyncfontfamilyorfontmap-source). After you set up the config plugin and run [prebuild](/workflow/continuous-native-generation/#usage), you can render custom fonts right away. The plugin can be configured in different ways, see the [Fonts](/develop/user-interface/fonts/#with-expo-font-config-plugin) guide on how to use it.

<ConfigPluginExample>

```json app.json
{
  "expo": {
    "plugins": [
      [
        "expo-font",
        {
          /* @info The path to the font file is relative to the project's root. */
          "fonts": ["./path/to/file.ttf"],
          /* @end */
          "android": {
            "fonts": [
              {
                "fontFamily": "Source Serif 4",
                "fontDefinitions": [
                  {
                    "path": "./path/to/SourceSerif4-ExtraBold.ttf",
                    "weight": 800
                  }
                ]
              }
            ]
          }
        }
      ]
    ]
  }
}
```

</ConfigPluginExample>

<ConfigPluginProperties
  properties={[
    {
      name: 'fonts',
      description:
        'An array of font definitions to link to the native project. The paths should be relative to the project root. On Android, the file name becomes the font family name. On iOS, the font family name is always taken directly from the font file and may not be the same as the file name &mdash; follow the [naming advice](/develop/user-interface/fonts/#how-to-determine-which-font-family-name-to-use) or use [`getLoadedFonts`](#getloadedfonts) to see what fonts are available.',
      default: '[]',
    },
    {
      name: 'android',
      description:
        'An array of font definitions to link to the native project on Android. Use the object syntax to embed [xml fonts](https://developer.android.com/develop/ui/views/text-and-emoji/fonts-in-xml) with custom family name.',
      default: '[]',
    },
    {
      name: 'ios',
      description:
        'An array of font file paths to link to the native project on iOS. The font family name is taken directly from the font file.',
      default: '[]',
    },
  ]}
/>

<ConfigReactNative>

- **Android:** Copy font files to **android/app/src/main/assets/fonts**.
- **iOS**: See [Adding a Custom Font to Your App](https://developer.apple.com/documentation/uikit/adding-a-custom-font-to-your-app) in the Apple Developer documentation.

</ConfigReactNative>

## Usage

If you don't want to use the [config plugin](#configuration-in-app-config), you can load a font at runtime with the `useFonts` hook, as shown in the snippet:

<SnackInline label="Example of loading and using a custom font" dependencies={['expo-font', 'expo-splash-screen']} files={{ 'assets/fonts/Inter-Black.otf': 'https://snack-code-uploads.s3.us-west-1.amazonaws.com/~asset/44b1541a96341780b29112665c66ac67' }}>

```tsx
/* @info Import useFonts hook from 'expo-font'. */ import { useFonts } from 'expo-font'; /* @end */
/* @info Also, import SplashScreen so that when the fonts are not loaded, we can continue to show SplashScreen. */ import * as SplashScreen from 'expo-splash-screen'; /* @end */
import { useEffect } from 'react';
import { Text, View, StyleSheet } from 'react-native';

/* @info This prevents SplashScreen from auto hiding while the fonts are loaded. */
SplashScreen.preventAutoHideAsync();
/* @end */

export default function App() {
  // Use `useFonts` only if you can't use the config plugin.
  const [loaded, error] = useFonts({
    'Inter-Black': require('./assets/fonts/Inter-Black.otf'),
  });

  useEffect(() => {
    if (loaded || error) {
      /* @info After the custom fonts have loaded, we can hide the splash screen and display the app screen. */
      SplashScreen.hideAsync();
      /* @end */
    }
  }, [loaded, error]);

  if (!loaded && !error) {
    return null;
  }

  return (
    <View style={styles.container}>
      <Text style={{ fontFamily: 'Inter-Black', fontSize: 30 }}>Inter Black</Text>
      <Text style={{ fontSize: 30 }}>Platform Default</Text>
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
  },
});
```

</SnackInline>

## API

```js
import * as Font from 'expo-font';
```

<APISection packageName="expo-font" />

## Error codes

| Code                | Description                                                       |
| ------------------- | ----------------------------------------------------------------- |
| ERR_FONT_API        | If the arguments passed to `loadAsync` are invalid.               |
| ERR_FONT_SOURCE     | The provided resource was of an incorrect type.                   |
| ERR_WEB_ENVIRONMENT | The browser's `document` element doesn't support injecting fonts. |
| ERR_DOWNLOAD        | Failed to download the provided resource.                         |
| ERR_FONT_FAMILY     | Invalid font family name was provided.                            |
| ERR_UNLOAD          | Attempting to unload fonts that haven't finished loading yet.     |
